package com.jacky.flutter_screen_recording;

import static android.content.ComponentCallbacks2.*;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.enotary.mobile.screen.FaXinServiceConnection;
import com.jacky.log.Logger;
import com.meituan.flutter_logan.FlutterLoganPlugin;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.PluginRegistry;

public class FlutterScreenRecordingPlugin implements FlutterPlugin, ActivityAware,
        MethodChannel.MethodCallHandler, PluginRegistry.ActivityResultListener {

    static FlutterScreenRecordingPlugin mPlugin;

    private static final int MODE_SCREEN = 1132; //为第三方使用录屏功能，提供权限申请的过渡页

    private ActivityPluginBinding mBinding = null;
    private MethodChannel channel = null;

    private RecordServiceConnection _connection;
    private MediaProjectionManager mMediaManager;

//    public static void registerWith(PluginRegistry.Registrar registrar) {
//        FlutterScreenRecordingPlugin plugin = new FlutterScreenRecordingPlugin();
//        plugin.channel = new MethodChannel(registrar.messenger(), "com.jacky/flutter_screen_recording");
//        plugin.channel.setMethodCallHandler(plugin);
//        registrar.addActivityResultListener(plugin);
//    }

    @Override
    public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
        channel = new MethodChannel(binding.getBinaryMessenger(), "com.jacky/flutter_screen_recording");
        channel.setMethodCallHandler(this);
    }

    @Override
    public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
        channel.setMethodCallHandler(null);
        channel = null;
    }

    public void requestMediaProjection() {
        Activity activity = mBinding.getActivity();
        mMediaManager = (MediaProjectionManager) activity.getSystemService(Context.MEDIA_PROJECTION_SERVICE);
        activity.startActivityForResult(mMediaManager.createScreenCaptureIntent(), MODE_SCREEN);
    }

    @Override
    public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
        mBinding = binding;
        binding.addActivityResultListener(this);
    }

    @Override
    public boolean onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        if (requestCode == MODE_SCREEN) {
            try {
                MediaProjection mediaProjection = mMediaManager == null ? null : mMediaManager.getMediaProjection(resultCode, data);
                if (mediaProjection == null) {
                    ScreenRecordService.screenFail(FaXinServiceConnection.ERR_AUTH);
                } else {
                    ScreenRecordService.authSuccess(mediaProjection);
                }
            } catch (Exception e) {
                RecordServiceConnection.sendLog(_connection, e);
                ScreenRecordService.screenFail(FaXinServiceConnection.ERR_UNKOWN);
            }
            mMediaManager = null;
            return true;
        }
        return false;
    }

    @Override
    public void onDetachedFromActivity() {
        stopScreen();
        mBinding.removeActivityResultListener(this);
        mBinding = null;
    }

    @Override
    public void onDetachedFromActivityForConfigChanges() {
        mBinding.removeActivityResultListener(this);
    }

    @Override
    public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
        mBinding = binding;
        mBinding.addActivityResultListener(this);
    }

    @Override
    public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
        String name = call.method;
        LogI("onMethodCall:Name= " + name);
        if (call.arguments != null) {
            LogI("onMethodCall:Arguments==" + call.arguments);
        }
        switch (name) {
            case "moveTaskToBack":
                Boolean nonRoot = call.argument("nonRoot");
                Activity act = mBinding.getActivity();
                result.success(act != null && act.moveTaskToBack(nonRoot != null && nonRoot));
                break;
            case "bindScreenRecord":
                mPlugin = this;
                if(_connection != null) return;

                boolean self = call.argument("self");
                _connection = new RecordServiceConnection(channel);
                if (self) {
                    _connection.bindSelfService(mBinding.getActivity(), ScreenRecordService.class);
                } else {
                    _connection.bindService(mBinding.getActivity());
                }
                break;
            case "startScreenRecord":
                if (_connection != null) {
                    String mp4Dir = call.argument("mp4Dir");
                    int maxRecordSecond = call.argument("maxRecordSecond");
                    long serverTime = call.argument("serverTime");
                    boolean checkSim = call.argument("checkSim");
                    int macState = call.argument("macState");
                    String digest = call.argument("digest");
                    String evidId = call.argument("evidId");
                    _connection.evidId = evidId;
                    _connection.startScreen(mp4Dir, maxRecordSecond, serverTime, false, !checkSim, macState, digest);
                } else {
                    LogI("screen service no connect.");
                }
                break;
            case "stopScreenRecord":
                stopScreen();
                break;
            case "unbindScreenRecord":
                if (_connection != null) _connection.release();
                _connection = null;
                mPlugin = null;
                break;
            case "isScreenRecording":
                result.success(_connection != null && _connection.isScreenRecording());
                break;
            case "isIgnoreBatteryOptimizations":
                result.success(AppUtils.isIgnoreBatteryOptimizations(mBinding.getActivity()));
                break;
            case "requestIgnoreBatteryOptimizations":
                result.success(AppUtils.requestIgnoreBatteryOptimizations(mBinding.getActivity()));
                break;
            case "toBootManagerActivity":
                Boolean noWayToSetting = call.argument("noWayToSetting");
                result.success(AppUtils.toBootManagerActivity(mBinding.getActivity(),noWayToSetting));
                break;
            case "hasPackagesPermission":
                result.success(AppUtils.hasPackagesPermission(mBinding.getActivity()));
                break;
            case "requestPackagesPermission":
                result.success(AppUtils.requestPackagesPermission(mBinding.getActivity()));
                break;
            default:
                result.notImplemented();
                break;
        }
    }

    private void stopScreen() {
        if (_connection != null) {
            _connection.stopScreen();
        }
    }

    private void LogI(String msg) {
        Logger.i(msg);
    }

    public static void lowMemory(Context context, String msg) {
        lowMemory(context, 0, msg);
    }

    public static void lowMemory(Context context, int level, String msg) {
        if (level == TRIM_MEMORY_UI_HIDDEN
                || level == TRIM_MEMORY_RUNNING_MODERATE
                || level == TRIM_MEMORY_RUNNING_LOW
                || level == TRIM_MEMORY_RUNNING_CRITICAL)
            return;
        Logger.i(msg);
        boolean b = ScreenRecordService.isScreenRunning();
        if(b) {
            String toast;
            if(level == TRIM_MEMORY_BACKGROUND)
                toast = "内存紧张，请移除其他后台应用或结束屏幕录制";
            else toast = "应用内存不足，请尽快结束屏幕录制";
            AppUtils.showToast(context,  toast);
            try {
                FlutterLoganPlugin.w(msg + ScreenRecordService.mp4Duration(), 3);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
